package com.uab.ia;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.android.dataframework.DataFramework;
import com.android.dataframework.Entity;
import com.uab.ia.adapters.CaminoAdapter;
import com.uab.ia.adapters.SpinnerEstacionesAdapter;
import com.uab.ia.entidades.Camino;
import com.uab.ia.entidades.Conexion;
import com.uab.ia.entidades.Estacion;
import com.uab.ia.entidades.Node;
import com.uab.ia.utils.AEstrella;
import com.uab.ia.utils.AEstrella.OnAEstrellaListener;
import com.uab.ia.utils.AEstrellaParadas;
import com.uab.ia.utils.AEstrellaParadas.OnAEstrellaParadasListener;
import com.uab.ia.utils.AEstrellaTransbordo;
import com.uab.ia.utils.AEstrellaTransbordo.OnAEstrellaTransbordoListener;
import com.uab.ia.utils.AsyncTaskBBDD;
import com.uab.ia.utils.AsyncTaskBBDD.OnBBDDChargedListener;
import com.uab.ia.utils.Utils;

public class XarxaTransportActivity extends Activity implements
		OnClickListener, OnAEstrellaListener, OnAEstrellaTransbordoListener,
		OnBBDDChargedListener, OnAEstrellaParadasListener {

	private static final String TAG = "IA";
	/**
	 * Variables
	 */

	private Activity act;
	private SharedPreferences prefs;
	private ProgressDialog pDialog;
	private Utils utils;
	private TextView text;
	private Button btn1;
	private Button btn2;
	private Button btn3;
	private Spinner spin1;
	private Spinner spin2;
	private ProgressDialog pDialog2;
	private AEstrella aEstrella;
	private ListView lista;
	private Button btn4;
	private AEstrellaTransbordo aEstrellaTrans;

	private String aStarType = "simple";
	private AEstrellaParadas aEstrellaParadas;
	private View btn5;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		defineVars();
		getViews();
		setListeners();
		setInitialData();
	}

	/**
	 * This method defines enviornment vars
	 */

	private void defineVars() {
		act = this;
		utils = Utils.getInstance();
	}

	/**
	 * This method shows dialod while charging data
	 */

	private void setInitialData() {
		prefs = getSharedPreferences("preferencias", MODE_PRIVATE);

		if (!prefs.getBoolean("CARGADO", false)) {
			pDialog = new ProgressDialog(this);
			pDialog.setTitle("Cargando datos");
			pDialog.setMessage("Los datos estan siendo transferidos a la base de datos.");
			pDialog.setCancelable(false);
			pDialog.show();
		}

		AsyncTaskBBDD cargadorBBDD = new AsyncTaskBBDD();
		cargadorBBDD.setListener(this);
		cargadorBBDD.execute(act);

		utils.setPrefs(prefs);
	}

	/**
	 * This method get Views in layout
	 */

	private void getViews() {
		text = (TextView) findViewById(R.id.textView);
		text.setVisibility(View.GONE);
		btn1 = (Button) findViewById(R.id.button1);
		btn2 = (Button) findViewById(R.id.button2);
		btn3 = (Button) findViewById(R.id.button3);
		btn4 = (Button) findViewById(R.id.button4);
		btn5 = (Button) findViewById(R.id.button5);
		spin1 = (Spinner) findViewById(R.id.spinner1);
		spin2 = (Spinner) findViewById(R.id.spinner2);
		lista = (ListView) findViewById(R.id.listView);
	}

	/**
	 * This method set data in spinners
	 */

	private void setData() {
		List<Entity> entidades = DataFramework.getInstance().getEntityList(
				"estacion");
		ArrayList<Estacion> estaciones = new ArrayList<Estacion>();

		for (Entity ent : entidades) {
			estaciones.add(new Estacion(ent));
		}

		SpinnerEstacionesAdapter adapter = new SpinnerEstacionesAdapter(act,
				estaciones);

		spin1.setAdapter(adapter);
		spin2.setAdapter(adapter);
	}

	/**
	 * Need to explain this?
	 */

	private void setListeners() {
		btn1.setOnClickListener(this);
		btn2.setOnClickListener(this);
		btn3.setOnClickListener(this);
		btn4.setOnClickListener(this);
		btn5.setOnClickListener(this);
	}

	/**
	 * This method allows re-run AEstrella
	 */

	private void declararAE() {
		if (aStarType.equals("simple")) {
			aEstrella = new AEstrella();
			aEstrella.setListener(this);
		} else if (aStarType.equals("trans")) {
			aEstrellaTrans = new AEstrellaTransbordo();
			aEstrellaTrans.setListener(this);
		} else if (aStarType.equals("paradas")) {
			aEstrellaParadas = new AEstrellaParadas();
			aEstrellaParadas.setListener(this);
		}
	}

	/**
	 * This method shows distance
	 * 
	 * @param id1
	 *            id of station 1
	 * @param id2
	 *            is od station 2
	 */

	private void mostrarDistancia(long id1, long id2) {
		// Nuevo
		Estacion e1 = new Estacion(id1);
		Estacion e2 = new Estacion(id2);

		Double valor = utils.getDistanceBetweenEstaciones(id1, id2);

		text.setText("Distancia entre " + e1.getNombre() + " y "
				+ e2.getNombre() + ":\n\n\t" + valor.toString());

		text.setVisibility(View.VISIBLE);
	}

	/**
	 * This method shows time
	 * 
	 * @param id1
	 *            id of station 1
	 * @param id2
	 *            is of station 2
	 */

	private void mostrarTemps(long id1, long id2) {
		// Nuevo
		Estacion e1 = new Estacion(id1);
		Estacion e2 = new Estacion(id2);

		Double valor = utils.getTimeBetweenEstaciones(id1, id2);

		text.setText("Tiempo entre " + e1.getNombre() + " y " + e2.getNombre()
				+ ":\n\n\t" + valor.toString());

		text.setVisibility(View.VISIBLE);
	}

	public void onClick(View v) {

		final long start = spin1.getSelectedItemId();
		final long end = spin2.getSelectedItemId();

		if (v.getId() == R.id.button1) {
			mostrarDistancia(spin1.getSelectedItemId(),
					spin2.getSelectedItemId());
		} else if (v.getId() == R.id.button2) {
			mostrarTemps(spin1.getSelectedItemId(), spin2.getSelectedItemId());
		} else if (v.getId() == R.id.button3) {

			aStarType = "simple";

			declararAE();

			pDialog2.show();
			aEstrella.execute(start, end);
		} else if (v.getId() == R.id.button4) {

			aStarType = "trans";

			declararAE();

			pDialog2.show();
			aEstrellaTrans.execute(start, end);
		} else if (v.getId() == R.id.button5) {

			aStarType = "paradas";

			declararAE();

			pDialog2.show();
			aEstrellaParadas.execute(start, end);
		}
	}

	/**
	 * This method make something if Camino is founded
	 * 
	 * @param c
	 *            Camino founded
	 * @param start
	 *            id station 1
	 * @param end
	 *            id station 2
	 */

	private void printarLista(Camino o, long start, long end) {
		pDialog2.dismiss();
		declararAE();

		/*
		 * Emparejar estaciones
		 */
		ArrayList<Conexion> parejas = new ArrayList<Conexion>();
		Node hijo = o.getRuta().get(0);

		while (hijo.getParent() != null) {
			Log.i(TAG, hijo.toString());
			parejas.add(0, utils.getConexion(hijo.getParent().id, hijo.id));
			hijo = hijo.getParent();
		}

		CaminoAdapter caminoAdapter = new CaminoAdapter(act, parejas);
		lista.setAdapter(caminoAdapter);
	}

	/**
	 * This method make something if Camino isn't founded
	 * 
	 * @param start
	 *            id station 1
	 * @param end
	 *            id station 2
	 */

	public void OnNoHayCamino(long start, long end) {
		pDialog2.dismiss();
		declararAE();
		text.setVisibility(View.VISIBLE);
		text.setGravity(Gravity.CENTER);
		text.setText("No se ha encontrado camino");
		lista.invalidate();
	}

	/**
	 * This method executes when BBDD is loaded
	 */

	public void onBBDChardedDone() {
		Editor editor = prefs.edit();
		editor.putBoolean("CARGADO", true);
		editor.commit();
		if (pDialog != null && pDialog.isShowing()) {
			pDialog.cancel();
		}
		utils.getVelMaxTren();

		setData();

		utils.setPrefs(prefs);
		utils.getVelMaxTren();

		pDialog2 = new ProgressDialog(act);
		pDialog2.setMessage("Calculando A*");

		declararAE();
	}

	public void onBBDChardedError() {
		showError();
	}

	private void showError() {
		Toast.makeText(act, R.string.error_bbdd, Toast.LENGTH_SHORT);
	}

	public void OnCaminoEncontrado(Camino c, long start, long end) {
		printarLista(c, start, end);

		printarExtras(c);
	}

	private void printarExtras(Camino c) {

		Node hijo = c.getRuta().get(0);

		if (aStarType.equals("simple")) {
			text.setText("Tiempo: " + hijo.getCosteT());
		} else if (aStarType.equals("trans")) {
			text.setText("Transbordos: " + c.getTransborodos());
		} else if (aStarType.equals("paradas")) {
			text.setText("Num Paradas: " + c.getnParadas());
		}

		text.setVisibility(View.VISIBLE);
		text.setGravity(Gravity.CENTER);
	}

	@Override
	public void onBackPressed() {
		if (aStarType.equals("simple") && aEstrella != null) {
			aEstrella.cancel(true);
		} else if (aStarType.equals("trans") && aEstrellaTrans != null) {
			aEstrellaTrans.cancel(true);
		}
		super.onBackPressed();
	}

	@Override
	protected void onStop() {
		if (aStarType.equals("simple") && aEstrella != null) {
			aEstrella.cancel(true);
		} else if (aStarType.equals("trans") && aEstrellaTrans != null) {
			aEstrellaTrans.cancel(true);
		}
		super.onStop();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		if (item.getItemId() == R.id.item) {
			Intent intent = new Intent(this, AboutActivity.class);
			startActivity(intent);
		}

		return super.onOptionsItemSelected(item);
	}
}